package com.wantupai.translate.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.view.TextureView;
import android.widget.Toast;

import com.tencent.mm.opensdk.utils.Log;
import com.wantupai.translate.utils.MyLog;
import com.wantupai.translate.utils.ToastUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.List;

public class SspCameraPreview extends TextureView implements TextureView.SurfaceTextureListener,
        Camera.PictureCallback, Camera.ShutterCallback {

    private Camera mCamera;
    private int index = Camera.CameraInfo.CAMERA_FACING_BACK;
    private String flashStatu = Camera.Parameters.FLASH_MODE_OFF;//默认关闭
    private OnPictureTakenListener onPictureTakenListener;
    private SurfaceTexture mSurface;
    private int maxZoom;
    private int nowZoom;

    public SspCameraPreview(Context context) {
        this(context, null);
    }

    public SspCameraPreview(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SspCameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void init(int index) {
        this.index = index;
        setSurfaceTextureListener(this);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mSurface = surface;
        openCamera();
    }

    public void openCamera() {
        try {
            // 1.打开相机
            mCamera = getCameraInstance(getContext(), index);
            if (mCamera != null) {
                // 2.设置相机参数
                Camera.Parameters parameters = mCamera.getParameters();
                // 3.调整预览方向
                mCamera.setDisplayOrientation(90);
                // 4.设置预览尺寸
                Point bestPreview = findBestPreviewSizeValue(parameters.getSupportedPreviewSizes());
                if (bestPreview != null) {
                    parameters.setPreviewSize(bestPreview.x, bestPreview.y);
//                    // 4.1设置照片尺寸 不能跟预览尺寸一样，预防设置失败
                    Point bestPicture = findBestPreviewSizeValue(parameters.getSupportedPictureSizes());
                    if (bestPicture != null) {
                        parameters.setPictureSize(bestPicture.x, bestPicture.y);
                    }
                }
                // 5.调整拍照图片方向
                if (index == Camera.CameraInfo.CAMERA_FACING_BACK) parameters.setRotation(90);
                if (index == Camera.CameraInfo.CAMERA_FACING_FRONT) parameters.setRotation(270);
                // 7.设置相机自动对焦
                List<String> focusModes = parameters.getSupportedFocusModes();
                for (String mode : focusModes) {
                    if (mode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                        break;
                    }
                }
                if (parameters.isSmoothZoomSupported()) {
                    maxZoom = parameters.getMaxZoom();
                    nowZoom = parameters.getZoom();
                }
                mCamera.setParameters(parameters);
                // 6.开始相机预览
                mCamera.setPreviewTexture(mSurface);
                mCamera.startPreview();
//                // 8.没有这行代码相机会无法连续对焦
                mCamera.cancelAutoFocus();
            }
        } catch (Exception e) {
            e.printStackTrace();
            ToastUtils.show(e.toString());
        }
    }

    protected static Point findBestPreviewSizeValue(List<Camera.Size> sizeList) {
        int bestX = 0;
        int bestY = 0;
        int size = 0;
        for (Camera.Size nowSize : sizeList) {
            int newX = nowSize.width;
            int newY = nowSize.height;
            int newSize = Math.abs(newX * newX) + Math.abs(newY * newY);
            float ratio = (float) (newY * 1.0 / newX);
            if (newSize >= size && ratio != 0.75) {//确保图片是16:9
                bestX = newX;
                bestY = newY;
                size = newSize;
            }
        }
        if (bestX > 0 && bestY > 0) {
            return new Point(bestX, bestY);
        }
        return null;
    }


    private Camera.Size changePreviewSize(Camera camera, int viewWidth, int viewHeight) {
        Camera.Parameters parameters = camera.getParameters();
        List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
        Camera.Size closelySize = null;//储存最合适的尺寸
        for (Camera.Size size : sizeList) { //先查找preview中是否存在与surfaceview相同宽高的尺寸
            if (((size.width == viewWidth) && (size.height == viewHeight)) || ((size.width == viewHeight) && (size.height == viewWidth))) {
                closelySize = size;
            }
        }
        if (closelySize == null)
            closelySize = getBestSize(camera.getParameters().getSupportedPreviewSizes());
        return closelySize;
    }

    /*获取最合适高清的Size*/
    private Camera.Size getBestSize(List<Camera.Size> sizes) {
        Camera.Size max = sizes.get(0);
        for (int i = 1; i < sizes.size(); i++) {
            int nows = sizes.get(i).width * sizes.get(i).height;
            int maxs = max.width * max.height;
            if (nows > maxs) {
                max = sizes.get(i);
            }
        }
        return max;
    }


    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if (success) {
                    mCamera.cancelAutoFocus();
                    doAutoFocus();
                }
            }
        });
    }

    /*设置相机自动对焦，提高清晰度*/
    private void doAutoFocus() {
        final Camera.Parameters parameters = mCamera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.setParameters(parameters);
        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if (success) {
                    camera.cancelAutoFocus();// 只有加上了这一句，才会自动对焦。
                    Camera.Parameters parameters = camera.getParameters();
                    List<String> focusModes = parameters.getSupportedFocusModes();
                    for (String mode : focusModes) {
                        if (mode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                            break;
                        }
                    }
                    camera.setParameters(parameters);
                }
            }
        });
    }


    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        releaseCamera();
        return true;
    }

    public void releaseCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }


    public static Camera getCameraInstance(Context context, int i) {
        Camera c = null;
        try {
            c = Camera.open(i);
        } catch (Exception e) {
            Toast.makeText(context, "相机打开失败", Toast.LENGTH_SHORT).show();
        }
        return c;
    }

    public void takePicture(OnPictureTakenListener listener) {
        if (listener != null) {
            onPictureTakenListener = listener;
            if (mCamera != null) {
                //takePicture方法时需要传入三个参数
                //1、拍照瞬间调用
                //2、获得没有压缩过的图片数据
                //3、创建jpeg图片回调数据对象
                mCamera.takePicture(null, null, this);
            } else {
                onPictureTakenListener.onFailed("拍照失败");
            }
        }
    }

    public void setZoom(int progress) {
        if (mCamera != null) {
            Camera.Parameters parameters = mCamera.getParameters();
            int max = parameters.getMaxZoom();
            parameters.setZoom((int) (progress * 1.0f / (max * 100) * max));
            MyLog.e("cameraPreview","最大值" + max + "        进度= " + (int) (progress * 1.0f / (max * 100) * max));
            mCamera.setParameters(parameters);
        }
    }

    public int getMaxZoom() {
        return maxZoom;
    }


    public void switchCamera() {
        releaseCamera();
        if (this.index == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            this.index = Camera.CameraInfo.CAMERA_FACING_BACK;
        } else {
            this.index = Camera.CameraInfo.CAMERA_FACING_FRONT;
        }
        openCamera();
    }

    public int getCameraIndex() {
        return this.index;
    }

    public void switchFlash() {
        if (this.index == Camera.CameraInfo.CAMERA_FACING_BACK) {
            releaseCamera();
            if (flashStatu.equals(Camera.Parameters.FLASH_MODE_OFF)) {
                flashStatu = Camera.Parameters.FLASH_MODE_TORCH;
            } else {
                flashStatu = Camera.Parameters.FLASH_MODE_OFF;
            }
            openCamera();
        }
    }

    public boolean openLight() {
        try {
            if (mCamera != null) {
//                mCamera.startPreview();
                Camera.Parameters parameter = mCamera.getParameters();
                parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameter);
            } else
                return false;
        } catch (Exception ex) {
            Log.i("090909", ex.getMessage());
            return false;
        }
        return true;
    }

    public boolean closeLight() {
        try {
            if (mCamera != null) {
                Camera.Parameters parameter = mCamera.getParameters();
                parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(parameter);
            } else
                return false;
        } catch (Exception ex) {
            Log.i("090909", ex.getMessage());
            return false;
        }
        return true;
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
//        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        Bitmap bitmap = byteToBitmap(data);
        if (index == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            bitmap = reversalBitmap(bitmap, -1, 1);
        }
        if (onPictureTakenListener != null) {
            onPictureTakenListener.onSuccess(bitmap);
        }

        // 使拍照结束后重新预览
        releaseCamera();
        openCamera();
    }

    /*防止内存溢出，设置一定大小的分辨率可以防止BitmapFactory.decodeByteArray 的OOM*/
    @SuppressWarnings("unchecked")
    public static Bitmap byteToBitmap(byte[] imgByte) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;
        InputStream input = new ByteArrayInputStream(imgByte);
        SoftReference softRef = new SoftReference(BitmapFactory.decodeStream(input, null, options));
        Bitmap bitmap = (Bitmap) softRef.get();
        try {
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    private Bitmap reversalBitmap(Bitmap srcBitmap, float sx, float sy) {
        Bitmap cacheBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        int w = cacheBitmap.getWidth();
        int h = cacheBitmap.getHeight();
        Canvas canvas = new Canvas(cacheBitmap);
        Matrix matrix = new Matrix();
        matrix.postScale(sx, sy);
        Bitmap bitmap = Bitmap.createBitmap(srcBitmap, 0, 0, w, h, matrix, true);
        canvas.drawBitmap(bitmap, new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()), new Rect(0, 0, w, h), null);
        return bitmap;
    }

    @Override
    public void onShutter() {

    }

    public interface OnPictureTakenListener {
        void onSuccess(Bitmap bitmap);

        void onFailed(String msg);
    }

}
